home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / Basic / Visual Basic.60 / COMMON / TOOLS / VCM / VCM.MDB / VcmComponentContainer / 14_Cabinet / DBTREEVW.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1998-05-18  |  11.4 KB  |  458 lines

  1. // DBTreeVw.cpp : implementation file
  2. //
  3. // This is a part of the Microsoft Foundation Classes and
  4. // Templates (MFC&T).
  5. // Copyright (C) 1998 Microsoft Corporation
  6. // All rights reserved.
  7. //
  8. // This source code is only intended as a supplement to the
  9. // MFC&T Reference and related electronic documentation provided
  10. // with the library.  See these sources for detailed information
  11. // regarding the MFC&T product.
  12. //
  13.  
  14. #include "stdafx.h"
  15. #include "DBViewer.h"
  16. #include "dlgsql.h"
  17. #include "dbexcept.h"
  18. #include "errordlg.h"
  19.  
  20. #ifdef _DEBUG
  21. #define new DEBUG_NEW
  22. #undef THIS_FILE
  23. static char THIS_FILE[] = __FILE__;
  24. #endif
  25.  
  26. /////////////////////////////////////////////////////////////////////////////
  27. // CDBTreeView
  28.  
  29. IMPLEMENT_DYNCREATE(CDBTreeView, CTreeView)
  30.  
  31. CDBTreeView::CDBTreeView()
  32. {
  33.     m_pSession = NULL;
  34. }
  35.  
  36. CDBTreeView::~CDBTreeView()
  37. {
  38.     m_pSession = NULL;
  39. }
  40.  
  41.  
  42. BEGIN_MESSAGE_MAP(CDBTreeView, CTreeView)
  43.     //{{AFX_MSG_MAP(CDBTreeView)
  44.     ON_WM_CREATE()
  45.     ON_WM_SYSCOLORCHANGE()
  46.     ON_COMMAND(ID_QUERY_EDIT, OnQueryEdit)
  47.     //}}AFX_MSG_MAP
  48.     ON_COMMAND_RANGE(ID_TABLE_SCHEMA, ID_QUERY_RUN, OnPopupCommand)
  49.     ON_NOTIFY_REFLECT(TVN_KEYDOWN, OnKeyDown)
  50.     ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnNodeSelect)
  51.     ON_NOTIFY_REFLECT(NM_RCLICK, OnRightClick)
  52. END_MESSAGE_MAP()
  53.  
  54.  
  55. /////////////////////////////////////////////////////////////////////////////
  56. // CDBTreeView diagnostics
  57.  
  58. #ifdef _DEBUG
  59. void CDBTreeView::AssertValid() const
  60. {
  61.     CTreeView::AssertValid();
  62. }
  63.  
  64. void CDBTreeView::Dump(CDumpContext& dc) const
  65. {
  66.     CTreeView::Dump(dc);
  67. }
  68.  
  69. CDBViewDoc* CDBTreeView::GetDocument() // non-debug version is inline
  70. {
  71.     ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDBViewDoc)));
  72.     return (CDBViewDoc*)m_pDocument;
  73. }
  74. #endif //_DEBUG
  75.  
  76. /////////////////////////////////////////////////////////////////////////////
  77. // CDBTreeView message handlers
  78.  
  79. int CDBTreeView::OnCreate(LPCREATESTRUCT lpCreateStruct)
  80. {
  81.     lpCreateStruct->style |= TVS_HASLINES | TVS_HASBUTTONS;
  82.     if (CTreeView::OnCreate(lpCreateStruct) == -1)
  83.         return -1;
  84.  
  85.     GetDocument()->m_pTreeView = this;
  86.  
  87.     // Create the Image List
  88.     m_ctlImage.Create(IDB_IMAGELIST3, 16, 0, RGB(255,0,255));
  89.     m_ctlImage.SetBkColor(GetSysColor(COLOR_WINDOW));
  90.  
  91.     /// Attach image list to Tree
  92.     CTreeCtrlEx& ctlTree = (CTreeCtrlEx&) GetTreeCtrl();
  93.     ctlTree.SetImageList(&m_ctlImage);
  94.  
  95.     m_dropTarget.Register(this);
  96.  
  97.     return 0;
  98. }
  99.  
  100. void CDBTreeView::OnSysColorChange()
  101. {
  102.     CWnd::OnSysColorChange();
  103.  
  104.     // Reset the background color of our image list when notified
  105.     m_ctlImage.SetBkColor(GetSysColor(COLOR_WINDOW));
  106. }
  107.  
  108. void CDBTreeView::OnQueryEdit()
  109. {
  110.     USES_CONVERSION;
  111.     ASSERT(m_pSession);
  112.     CListCtrlEx&        ctlList = (CListCtrlEx&) GetDocument()->m_pListView->GetListCtrl();
  113.  
  114.     CDlgSQL dlgSQL;
  115.     dlgSQL.m_bEditMode = TRUE;
  116.  
  117.     // GetString
  118.     if (dlgSQL.DoModal() != IDOK)
  119.         return;
  120.     TRY
  121.     {
  122.         CDBPropSet propset(DBPROPSET_ROWSET);
  123.         propset.AddProperty(DBPROP_IRowsetChange, true);
  124.         propset.AddProperty(DBPROP_UPDATABILITY,
  125.                     DBPROPVAL_UP_INSERT | DBPROPVAL_UP_CHANGE | DBPROPVAL_UP_DELETE);
  126.  
  127.         // Open but don't bind.
  128.         CCommand<CManualAccessor> rs;
  129.         if (rs.Open(*m_pSession, dlgSQL.m_strSQL, &propset, NULL,
  130.                 DBGUID_DBSQL, FALSE) != S_OK)
  131.         {
  132.             AfxMessageBox(_T("Couldn't open rowset"));
  133.             return;
  134.         }
  135.  
  136.         // If a valid rowset is not returned (i.e. like running an INSERT
  137.         // statement, then exit the routine
  138.         if (rs.m_spRowset == NULL)
  139.         {
  140.             GetDocument()->m_pListView->UpdateWindow();
  141.             PopulateTree();
  142.             AfxMessageBox(IDS_SUCCESSFUL);
  143.             return;
  144.         }
  145.  
  146.         // Get the column information
  147.         ULONG ulColumns             = 0;
  148.         DBCOLUMNINFO* pColumnInfo   = NULL;
  149.         LPOLESTR pStrings           = NULL;
  150.         if (rs.GetColumnInfo(&ulColumns, &pColumnInfo, &pStrings) != S_OK)
  151.             AfxThrowOLEDBException(rs.m_spRowset, IID_IColumnsInfo);
  152.  
  153.         struct MYBIND* pBind = new MYBIND[ulColumns];
  154.         rs.CreateAccessor(ulColumns, &pBind[0], sizeof(MYBIND)*ulColumns);
  155.         for (ULONG l=0; l<ulColumns; l++)
  156.             rs.AddBindEntry(l+1, DBTYPE_STR, sizeof(TCHAR)*40, &pBind[l].szValue,
  157.                 NULL, &pBind[l].dwStatus);
  158.         rs.Bind();
  159.  
  160.         // Display the data (to the maximum # of records allowed)
  161.         int nMaxRecords = ((CDBViewApp*)AfxGetApp())->m_nMaxRecords;
  162.         int nItem=0;
  163.         ULONG ulFields = rs.GetColumnCount();
  164.         GetDocument()->m_pListView->EraseList();
  165.         while(rs.MoveNext() == S_OK)
  166.         {
  167.             if (nItem < nMaxRecords)
  168.             {
  169.                 for (ULONG j=1; j<=ulFields; j++)
  170.                 {
  171.                     if (nItem == 0)
  172.                         ctlList.AddColumn(OLE2T(pColumnInfo[j-1].pwszName), j-1);
  173.  
  174.                     if (pBind[j-1].dwStatus == DBSTATUS_S_ISNULL)
  175.                     {
  176.                         ctlList.AddItem(nItem, j-1, _T(""));
  177.                     }
  178.                     else
  179.                     {
  180.                         LPTSTR lpszString = pBind[j-1].szValue;
  181.                         ctlList.AddItem(nItem, j-1, lpszString);
  182.                     }
  183.                 }
  184.                 nItem++;
  185.             }
  186.         }
  187.         CoTaskMemFree(pColumnInfo);
  188.         CoTaskMemFree(pStrings);
  189.         delete pBind;
  190.         pBind = NULL;
  191.     }
  192.     CATCH(COLEDBException, e)
  193.     {
  194.         CErrorsDialog dlg;
  195.         dlg.Init(e->m_lpUnk, e->m_iid);
  196.         dlg.DoModal();
  197.     }
  198.     END_CATCH
  199.  
  200.     GetDocument()->m_pListView->UpdateWindow();
  201. }
  202.  
  203. void CDBTreeView::OnPopupCommand(UINT nMenuID)
  204. {
  205.     CWaitCursor w;
  206.     GetDocument()->m_pListView->SetRedraw(FALSE);
  207.     switch (nMenuID)
  208.     {
  209.         case ID_TABLE_SCHEMA:
  210.             GetDocument()->m_pListView->ShowTableSchema(m_ItemSel.GetText());
  211.             break;
  212.         case ID_TABLE_DATA:
  213.             GetDocument()->m_pListView->ShowTableData(m_ItemSel.GetText());
  214.             break;
  215.         case ID_TABLE_INSERT:
  216.             GetDocument()->m_pListView->InsertRecord(m_ItemSel.GetText());
  217.             break;
  218.         case ID_QUERY_RUN:
  219.             GetDocument()->m_pListView->CallProcedure(m_ItemSel.GetText());
  220.             break;
  221.         default:
  222.             break;
  223.     }
  224.     GetDocument()->m_pListView->SetRedraw(TRUE);
  225. }
  226.  
  227. void CDBTreeView::OnKeyDown(NMHDR *pNotifyStruct,LRESULT *result)
  228. {
  229.     TV_KEYDOWN* pKeyDown = (TV_KEYDOWN *) pNotifyStruct;
  230.  
  231.     if (pKeyDown->wVKey == VK_DELETE)
  232.     {
  233.         BOOL bShowWarnings = ((CDBViewApp *)AfxGetApp())->m_bShowWarnings;
  234.         int retCode = IDYES;
  235.         if (bShowWarnings)
  236.         {
  237.             retCode = MessageBox(
  238.                 _T("Are you sure you want to delete this item ?"),
  239.                 _T("DBViewer - Warning"),MB_YESNO);
  240.         }
  241.         if (retCode == IDYES)
  242.             DeleteItem(m_ItemSel);
  243.     }
  244.     *result = 0;
  245. }
  246.  
  247. void CDBTreeView::OnNodeSelect(NMHDR *pNotifyStruct, LRESULT *result)
  248. {
  249.     *result = 0;
  250.  
  251.     if (m_bNoNotifications)
  252.         return;
  253.  
  254.     CTreeCtrlEx& ctlTree = (CTreeCtrlEx&) GetTreeCtrl();
  255.  
  256.     m_ItemSel = ctlTree.GetSelectedItem();
  257.  
  258.     UINT nImageID = m_ItemSel.GetImageID();
  259.     GetDocument()->m_pListView->SetRedraw(FALSE);
  260.  
  261.     switch (nImageID)
  262.     {
  263.         case IID_DATABASE:
  264. //          GetDocument()->m_pListView->ShowDatabase();
  265.             break;
  266.         case IID_TABLES:
  267.             GetDocument()->m_pListView->ShowTableSchema(NULL);
  268.             break;
  269.         case IID_TABLE:
  270.             GetDocument()->m_pListView->ShowTableSchema(m_ItemSel.GetText());
  271.             break;
  272.         case IID_FIELDS:
  273. //          GetDocument()->m_pListView->ShowFields(m_ItemSel.GetParent().GetText());
  274.             break;
  275.         case IID_FIELD:
  276. //          GetDocument()->m_pListView->ShowFields(m_ItemSel.GetParent().GetParent().GetText(),m_ItemSel.GetText());
  277.             break;
  278.         case IID_PROCEDURES:
  279.             GetDocument()->m_pListView->ShowProcedures(NULL);
  280.             break;
  281.         case IID_PROCEDURE:
  282.             GetDocument()->m_pListView->ShowProcedures(m_ItemSel.GetText());
  283.             break;
  284.         case IID_VIEWS:
  285.             GetDocument()->m_pListView->ShowTableSchema(NULL);
  286.             break;
  287.         case IID_VIEW:
  288.             GetDocument()->m_pListView->ShowTableSchema(m_ItemSel.GetText());
  289.             break;
  290.         case IID_INDEXES:
  291. //          GetDocument()->m_pListView->ShowIndexes(m_ItemSel.GetParent().GetText());
  292.             break;
  293.         case IID_INDEX:
  294. //          GetDocument()->m_pListView->ShowIndexes(m_ItemSel.GetParent().GetParent().GetText(),m_ItemSel.GetText());
  295.             break;
  296.     }
  297.  
  298.     GetDocument()->m_pListView->SetRedraw(TRUE);
  299. }
  300.  
  301. void CDBTreeView::OnRightClick(NMHDR *pNotifyStruct, LRESULT *result)
  302. {
  303.     CTreeCtrlEx& ctlTree = (CTreeCtrlEx&) GetTreeCtrl();
  304.  
  305.     UINT nFlags;
  306.     CPoint curPoint;
  307.     GetCursorPos(&curPoint);
  308.     ScreenToClient(&curPoint);
  309.     m_ItemSel = ctlTree.HitTest(curPoint, &nFlags);
  310.  
  311.     UINT nImageID = m_ItemSel.GetImageID();
  312.     switch (nImageID)
  313.     {
  314.         case IID_TABLE:
  315.         case IID_VIEW:
  316.             DoPopupMenu(IDR_POPUP_TABLE);
  317.             break;
  318.         case IID_PROCEDURE:
  319.             DoPopupMenu(IDR_POPUP_QUERY);
  320.             break;
  321.     }
  322.     *result = 0;
  323. }
  324.  
  325. void CDBTreeView::DoPopupMenu(UINT nMenuID)
  326. {
  327.     CMenu popMenu;
  328.  
  329.     popMenu.LoadMenu(nMenuID);
  330.  
  331.     CPoint posMouse;
  332.     GetCursorPos(&posMouse);
  333.  
  334.     popMenu.GetSubMenu(0)->TrackPopupMenu(0,posMouse.x,posMouse.y,this);
  335. }
  336.  
  337.  
  338. /////////////////////////////////////////////////////////////////////////////
  339. // CDBTreeView implementation functions
  340.  
  341. void CDBTreeView::PopulateTree()
  342. {
  343.     USES_CONVERSION;
  344.     CTreeCtrlEx& ctlTree = (CTreeCtrlEx&) GetTreeCtrl();
  345.     CTables*        pTableSet = NULL;
  346.     CProcedures*    pProcedureSet = NULL;
  347.  
  348.     m_bNoNotifications = TRUE;
  349.  
  350.     ctlTree.DeleteAllItems();
  351.     UpdateWindow();
  352.  
  353.     // If session is unavailable, we don't have a valid connection.  Therefore,
  354.     // there is no requirement to populate the tree
  355.     if (!m_pSession)
  356.         return;
  357.  
  358.     // Insert root node by call to tree object this time
  359.     tDatabase = ctlTree.GetRootItem().AddTail(GetDocument()->GetDSN(),
  360.                             IID_DATABASE);
  361.  
  362.     // From now on call via iterators
  363.     tTables = tDatabase.AddTail(_T("Tables"),IID_TABLES);
  364.     tProcedures = tDatabase.AddTail(_T("Procedures"),IID_PROCEDURES);
  365.  
  366.     BOOL bShowSystemObjects = ((CDBViewApp *)AfxGetApp())->m_bShowSystemObjects;
  367.  
  368.  
  369.     // List the tables in the data source
  370.     // Add an entry for all tables in the system
  371.     pTableSet = new CTables;
  372.  
  373.     // (can simply hard code max size)
  374.     char lpszType[64];
  375.  
  376.     // Set up type type to be retrieved
  377.     strcpy(lpszType, "TABLE");
  378.     if (((CDBViewApp *)AfxGetApp())->m_bShowSystemObjects)
  379.         strcat(lpszType, ",SYSTEM TABLE");
  380.  
  381.     if (pTableSet->Open(*m_pSession, NULL, NULL, NULL, lpszType) != S_OK)
  382.         return;
  383.  
  384.     while(pTableSet->MoveNext() == S_OK)
  385.     {
  386.         // We do not handle multi-word tables or procedures.  Normally,
  387.         // only Access handles these.
  388.         if (_tcschr(pTableSet->m_szName, _T(' ')) != NULL)
  389.             continue;
  390.  
  391.         if (_tcscmp(pTableSet->m_szType, _T("VIEW")) == 0)
  392.             AddItem(IID_VIEW, pTableSet->m_szName);
  393.         else
  394.             AddItem(IID_TABLE, pTableSet->m_szName);
  395.  
  396.     }
  397.  
  398.     delete pTableSet;
  399.     pTableSet = NULL;
  400.  
  401.     // List the stored procedures in the data source
  402.     // Get the Procedures Here
  403.     pProcedureSet = new CProcedures;
  404.  
  405.     // Get all procedure names
  406.     if (pProcedureSet->Open(*m_pSession) != S_OK)
  407.         return;
  408.  
  409.     while(pProcedureSet->MoveNext() == S_OK)
  410.     {
  411.         // We do not handle multi-word tables or procedures.  Normally,
  412.         // only Access handles these.
  413.         if (_tcschr(pProcedureSet->m_szName, _T(' ')) != NULL)
  414.             continue;
  415.  
  416.         AddItem(IID_PROCEDURE, pProcedureSet->m_szName);
  417.     }
  418.  
  419.     delete pProcedureSet;
  420.     pProcedureSet = NULL;
  421.  
  422.     tDatabase.Expand();
  423.     m_bNoNotifications = FALSE;
  424.     UpdateWindow();
  425. }
  426.  
  427. void CDBTreeView::AddItem(WORD nItemType, LPCTSTR lpszName)
  428. {
  429.     switch (nItemType)
  430.     {
  431.         case IID_TABLE:
  432.         {
  433.             tTable = tTables.AddTail(lpszName, IID_TABLE);
  434.             break;
  435.         }
  436.         case IID_PROCEDURE:
  437.         {
  438.             tProcedures.AddTail(lpszName, IID_PROCEDURE);
  439.             break;
  440.         }
  441.         case IID_VIEW:
  442.         {
  443.             tTable = tTables.AddTail(lpszName, IID_VIEW);
  444.             break;
  445.         }
  446.     }
  447. }
  448.  
  449. void CDBTreeView::DeleteItem(CTreeCursor& itemDelete)
  450. {
  451.     CString strText;
  452.     CCommand<CDynamicAccessor> rs;
  453.     strText.Format(_T("DROP TABLE %s"), itemDelete.GetText());
  454.     rs.Open(*m_pSession, strText, NULL, NULL, DBGUID_DEFAULT, false);
  455. //  rs.Close();
  456.     itemDelete.Delete();
  457. }
  458.